/**
 * 对内存页的分配与释放，伙伴系统主要的功能实现。
 * 
 * @todo 需要有个得到当前伙伴系统状态的接口。
 */
#ifndef _AHAMOLETT_PAGE_ALLOC_H_
#define _AHAMOLETT_PAGE_ALLOC_H_

#include <mm/mm_types.h>

/**
 * @brief 启动伙伴系统。
 * 
 * 将当前所有空闲页都加入伙伴系统的空闲列表中，关闭前期内存分配器，并启动伙伴系统。
 * 
 * 需要在 mem_zones_init 后启动。
 * 
 * @return int 启动成功返回0，失败返回-1。
 */
extern int activate_buddy_system(void);

/**
 * @brief 获得伙伴系统空闲链表的计数。
 * 
 * 给定一个内存区域，获得一个给定内存区域中给定阶数的空闲链表的计数。若输入的内存区域结构体不
 * 合法，或者输入的阶数过大，都直接返回0。
 * 
 * @param zone 空闲链表所在的内存区域结构体。
 * @param order 进行查看的空闲链表的阶数。
 * 
 * @return unsigned long 对应空闲列表内空闲页的个数。
 */
extern unsigned long get_free_list_count(
    struct zone_struct *zone, 
    unsigned long order
);

/**
 * @brief 通过伙伴系统分配order阶数个连续的内存页。
 * 
 * @param order 需要获得的连续内存页个数的阶数。
 * 
 * @return struct page_struct* 分配成功返回得到的内存页结构体，失败返回NULL。
 */
extern struct page_struct *__alloc_pages(unsigned long order);

/* 分配阶数为order个连续的内存页。 */
#define alloc_pages(order)  __alloc_pages(order)
/* 分配一个内存页。 */
#define alloc_page()    alloc_pages(0)

/**
 * @brief 释放order阶数个连续的内存页。
 * 
 * 进行释放的页必须按照 order 对齐，对应的所有内存页都必须位于同一个内存区域且都处于可被释放的
 * 状态。
 * 
 * @param page 进行释放的伙伴页。
 * @param order 需要释放的连续内存页个数的阶数。
 */
extern void __free_pages(struct page_struct *page, unsigned long order);

/* 释放阶数为order个连续的内存页。 */
#define free_pages(page, order) __free_pages(page, order)
/* 释放一个内存页。 */
#define free_page(page) free_pages(page, 0)

#endif
